﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.VisualBasic;

namespace AutoUpgrade
{
    internal class CommandHandle
    {
        /// <summary>
        /// 打包配置文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="description"></param>
        internal void Pack(string path, string description = "自动更新程序")
        {
            if (!path.EndsWith(@"\"))
                path += @"\";
            string app = System.Windows.Forms.Application.StartupPath;
            string filePath = System.IO.Path.Combine(path, "version.xml");
            string IgnorePath = app + @"\version.ignore";
            List<string> ignoreCollection = new List<string>();
            if (System.IO.File.Exists(IgnorePath))
                ignoreCollection = System.IO.File.ReadAllLines(IgnorePath).ToList();


            string configPath = System.IO.Path.Combine(app, "version.config");
            string config_host = default;
            string config_application = default;
            if (System.IO.File.Exists(configPath))
            {
                string xml = System.IO.File.ReadAllText(configPath);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);
                XmlNode[] configuration = doc.ChildNodes.OfType<XmlNode>().FirstOrDefault(x => x.Name == "configuration").ChildNodes.OfType<XmlNode>().ToArray();
                config_host = configuration.FirstOrDefault(x => x.Name == "host").InnerText.Trim();
                config_application = configuration.FirstOrDefault(x => x.Name == "application").InnerText.Trim();
            }
            System.Text.StringBuilder version = new System.Text.StringBuilder();
            version.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            version.AppendLine("<package>");
            version.AppendLine("  <metadata>");
            version.AppendLine("    <version>" + DateTime.Now.ToString("yy.MM.dd.HHmmss") + "</version>");
            version.AppendLine("    <description>" + description + "</description>");
            if (!string.IsNullOrEmpty(config_application))
                version.AppendLine("    <application>" + config_application + "</application>");
            if (!string.IsNullOrEmpty(config_host))
                version.AppendLine("    <host>" + config_host + "</host>");
            version.AppendLine("  </metadata>");
            version.AppendLine("  <files>");
            this.Build(version, path, path, ignoreCollection);
            version.AppendLine("  </files>");
            version.Append("</package>");
            System.IO.File.WriteAllText(filePath, version.ToString(), System.Text.Encoding.UTF8);
        }


        internal void Build(System.Text.StringBuilder version, string sourcePach, string path, List<string> ignoreCollection)
        {
            //string app = System.Windows.Forms.Application.StartupPath;
            foreach (string directory in System.IO.Directory.GetDirectories(path))
            {
                bool open = true;
                foreach (string ignore in ignoreCollection)
                {
                    if (!(ignore.Contains("*") || ignore.Contains("?")))
                    {
                        string ignorePath = System.IO.Path.Combine(sourcePach, ignore);
                        if ((directory == ignorePath))
                        {
                            open = false;
                            continue;
                        }
                    }
                }
                if (open)
                    this.Build(version, sourcePach, directory, ignoreCollection);
            }
            foreach (string file in System.IO.Directory.GetFiles(path))
            {
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);
                string filePath = fileInfo.FullName.Remove(0, sourcePach.Length);
                string version_str = fileInfo.LastWriteTime.ToString("yy.MM.dd.HHmmss");
                FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(fileInfo.FullName);
                if ((string.IsNullOrEmpty(versionInfo?.FileVersion) == false))
                    version_str = $"{versionInfo.FileMajorPart}.{versionInfo.FileMinorPart}.{versionInfo.FileBuildPart}.{versionInfo.ProductPrivatePart}";
                if (filePath == "version.xml" || filePath == "version.ignore" || filePath == "Upgrade.config" || fileInfo.Name.StartsWith("~"))
                    continue;
                bool open = true;

                //todo 此处未修改完成
                //foreach (string ignore in ignoreCollection)
                //{
                //    if (!(ignore.Contains("*") || ignore.Contains("?")))
                //    {
                //        
                //        string ignorePath = System.IO.Path.Combine(app, ignore);
                //        if (LikeOperator.LikeString(fileInfo.FullName, ignorePath, CompareMethod.Binary))
                //        {
                //            open = false;
                //            continue;
                //        }
                //    }
                //    else if (LikeOperator.LikeString(fileInfo.FullName, ignore, CompareMethod.Binary))
                //    {
                //        open = false;
                //        continue;
                //    }
                //}
                if (open && fileInfo.Attributes != System.IO.FileAttributes.Hidden)
                {
                    string md5 = GetMD5HashFromFile(fileInfo.FullName);
                    version.AppendLine($@"    <file name=""{filePath}"" version=""{version_str}"" size=""{fileInfo.Length }"" md5=""{md5}""/>");
                }
            }
        }

        /// <summary>
        /// 获取文件MD5值方法
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        internal string GetMD5HashFromFile(string fileName)
        {
            FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);
            file.Close();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }

        internal void Init()
        {
            string fileName = System.Windows.Forms.Application.StartupPath + @"\version.config";
            StringBuilder builder = new StringBuilder();
            builder.AppendLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
            builder.AppendLine(@"<configuration>");
            builder.AppendLine(@"     <!-- 请在此处输入程序的下载地址 -->");
            builder.AppendLine(@"     <host></host>");
            builder.AppendLine(@"     <!-- 需要启动的应用程序名称 -->");
            builder.AppendLine(@"     <application></application>");
            builder.AppendLine(@"</configuration>");
            System.IO.File.WriteAllText(fileName, builder.ToString());
        }

        /// <summary>
        /// 忽略
        /// </summary>
        /// <param name="path"></param>
        internal void Ignore(string path)
        {
            string IgnorePath;
            string app = System.Windows.Forms.Application.StartupPath;
            try
            {
                IgnorePath = System.IO.Path.Combine(app, path);
                if (System.IO.Directory.Exists(IgnorePath))
                    IgnorePath += "/";
                IgnorePath = IgnorePath.Remove(0, app.Length + 1);
            }
            catch (Exception)
            {
                IgnorePath = path;
            }

            string Ignoresetting = System.Windows.Forms.Application.StartupPath + @"\version.ignore";
            List<string> ignoreCollection = new List<string>();
            if (System.IO.File.Exists(Ignoresetting))
                ignoreCollection = System.IO.File.ReadAllLines(Ignoresetting).ToList();
            ignoreCollection.Add(IgnorePath);
            ignoreCollection = ignoreCollection.Distinct().ToList();
            System.IO.File.WriteAllLines(Ignoresetting, ignoreCollection);
        }

        internal void Run(params string[] commandLine)
        {
            GlobalSetting.Host = commandLine[0];
            GlobalSetting.StartupApplication = commandLine[1];
        }
    }
}
